﻿using System;
using System.Windows;
using System.Windows.Controls;
using NUnit.Framework;
using WPFCABShell.Shell.Services;

namespace WPFCABShell.UnitTest.Shell.Services
{
	[TestFixture]
	public sealed class GroupingItemsControlUIAdapterTest : UnitTest.Shared.UnitTest
	{
		private ItemsControl _itemsControl;
		private GroupingItemsControlUIAdapter _groupingItemsControlUIAdapter;

		protected override void SetUpCore()
		{
			base.SetUpCore();
			_itemsControl = new ItemsControl();
			_groupingItemsControlUIAdapter = new GroupingItemsControlUIAdapter(_itemsControl);
		}

		[Test]
		public void Add_ShouldAddItemToItemsControl()
		{
			DependencyObject item = new DependencyObject();
			Assert.IsFalse(_itemsControl.Items.Contains(item));
			_groupingItemsControlUIAdapter.Add(item);
			Assert.IsTrue(_itemsControl.Items.Contains(item));
		}

		[Test]
		public void Add_ShouldReturnItem()
		{
			DependencyObject item = new DependencyObject();
			Assert.AreSame(item, _groupingItemsControlUIAdapter.Add(item));
		}

		[Test]
		public void Remove_ShouldRemoveItemFromItemsControl()
		{
			DependencyObject item = new DependencyObject();
			_groupingItemsControlUIAdapter.Add(item);
			Assert.IsTrue(_itemsControl.Items.Contains(item));
			_groupingItemsControlUIAdapter.Remove(item);
			Assert.IsFalse(_itemsControl.Items.Contains(item));
		}

		[Test]
		public void Remove_ShouldDoNothingIfItemIsNotInItemsControl()
		{
			_groupingItemsControlUIAdapter.Remove(new DependencyObject());
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void GetGroupIndex_ShouldThrowIfItemIsNull()
		{
			GroupingItemsControlUIAdapter.GetGroupIndex(null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void SetGroupIndex_ShouldThrowIfItemIsNull()
		{
			GroupingItemsControlUIAdapter.SetGroupIndex(null, 10);
		}

		[Test]
		public void SetGroupIndex_ShouldSetGroupIndexOnGivenItem()
		{
			DependencyObject dependencyObject = new DependencyObject();
			Assert.IsNull(GroupingItemsControlUIAdapter.GetGroupIndex(dependencyObject));
			GroupingItemsControlUIAdapter.SetGroupIndex(dependencyObject, 10);
			Assert.AreEqual(10, GroupingItemsControlUIAdapter.GetGroupIndex(dependencyObject));
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void GetIndex_ShouldThrowIfItemIsNull()
		{
			GroupingItemsControlUIAdapter.GetIndex(null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void SetIndex_ShouldThrowIfItemIsNull()
		{
			GroupingItemsControlUIAdapter.SetIndex(null, 10);
		}

		[Test]
		public void SetIndex_ShouldSetGroupIndexOnGivenItem()
		{
			DependencyObject dependencyObject = new DependencyObject();
			Assert.IsNull(GroupingItemsControlUIAdapter.GetIndex(dependencyObject));
			GroupingItemsControlUIAdapter.SetIndex(dependencyObject, 10);
			Assert.AreEqual(10, GroupingItemsControlUIAdapter.GetIndex(dependencyObject));
		}

		[Test]
		[Ignore("Not yet implemented")]
		public void GroupIndex_GroupsShouldBeSeparatedBySeparators()
		{
			DependencyObject item1 = new DependencyObject();
			DependencyObject item2 = new DependencyObject();
			DependencyObject item3 = new DependencyObject();
			DependencyObject item4 = new DependencyObject();
			DependencyObject item5 = new DependencyObject();

			GroupingItemsControlUIAdapter.SetGroupIndex(item2, 1);
			GroupingItemsControlUIAdapter.SetGroupIndex(item3, 1);
			GroupingItemsControlUIAdapter.SetGroupIndex(item4, 50);
			GroupingItemsControlUIAdapter.SetGroupIndex(item5, 50);

			_groupingItemsControlUIAdapter.Add(item1);
			_groupingItemsControlUIAdapter.Add(item2);
			_groupingItemsControlUIAdapter.Add(item3);
			_groupingItemsControlUIAdapter.Add(item4);
			_groupingItemsControlUIAdapter.Add(item5);

			Assert.AreEqual(7, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[1]);
			Assert.AreSame(item2, _itemsControl.Items[2]);
			Assert.AreSame(item3, _itemsControl.Items[3]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[4]);
			Assert.AreSame(item4, _itemsControl.Items[5]);
			Assert.AreSame(item5, _itemsControl.Items[6]);
		}

		[Test]
		[Ignore("Not yet implemented")]
		public void GroupIndex_GroupsShouldDynamicallyReflectChangesInGroupIndex()
		{
			DependencyObject item1 = new DependencyObject();
			DependencyObject item2 = new DependencyObject();
			DependencyObject item3 = new DependencyObject();
			DependencyObject item4 = new DependencyObject();
			DependencyObject item5 = new DependencyObject();

			_groupingItemsControlUIAdapter.Add(item1);
			_groupingItemsControlUIAdapter.Add(item2);
			_groupingItemsControlUIAdapter.Add(item3);
			_groupingItemsControlUIAdapter.Add(item4);
			_groupingItemsControlUIAdapter.Add(item5);

			Assert.AreEqual(5, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);
			Assert.AreSame(item2, _itemsControl.Items[1]);
			Assert.AreSame(item3, _itemsControl.Items[2]);
			Assert.AreSame(item4, _itemsControl.Items[3]);
			Assert.AreSame(item5, _itemsControl.Items[4]);

			GroupingItemsControlUIAdapter.SetGroupIndex(item2, 1);
			GroupingItemsControlUIAdapter.SetGroupIndex(item3, 1);
			GroupingItemsControlUIAdapter.SetGroupIndex(item4, 50);
			GroupingItemsControlUIAdapter.SetGroupIndex(item5, 50);

			Assert.AreEqual(7, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[1]);
			Assert.AreSame(item2, _itemsControl.Items[2]);
			Assert.AreSame(item3, _itemsControl.Items[3]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[4]);
			Assert.AreSame(item4, _itemsControl.Items[5]);
			Assert.AreSame(item5, _itemsControl.Items[6]);

			//collapse items 4 and 5 into same group as items 2 and 3
			GroupingItemsControlUIAdapter.SetGroupIndex(item4, 1);
			GroupingItemsControlUIAdapter.SetGroupIndex(item5, 1);

			Assert.AreEqual(6, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[1]);
			Assert.AreSame(item2, _itemsControl.Items[2]);
			Assert.AreSame(item3, _itemsControl.Items[3]);
			Assert.AreSame(item4, _itemsControl.Items[4]);
			Assert.AreSame(item5, _itemsControl.Items[5]);
		}

		[Test]
		[Ignore("Not yet implemented")]
		public void Index_ShouldDictateSortOrderWithinGroup()
		{
			DependencyObject item1 = new DependencyObject();
			DependencyObject item2 = new DependencyObject();
			DependencyObject item3 = new DependencyObject();
			DependencyObject item4 = new DependencyObject();
			DependencyObject item5 = new DependencyObject();

			GroupingItemsControlUIAdapter.SetGroupIndex(item4, 1);
			GroupingItemsControlUIAdapter.SetGroupIndex(item5, 1);
			GroupingItemsControlUIAdapter.SetIndex(item1, 1);
			GroupingItemsControlUIAdapter.SetIndex(item2, 2);
			GroupingItemsControlUIAdapter.SetIndex(item3, 3);
			GroupingItemsControlUIAdapter.SetIndex(item5, 100);

			_groupingItemsControlUIAdapter.Add(item5);
			_groupingItemsControlUIAdapter.Add(item3);
			_groupingItemsControlUIAdapter.Add(item2);
			_groupingItemsControlUIAdapter.Add(item4);
			_groupingItemsControlUIAdapter.Add(item1);

			Assert.AreEqual(6, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);
			Assert.AreSame(item2, _itemsControl.Items[1]);
			Assert.AreSame(item3, _itemsControl.Items[2]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[3]);
			Assert.AreSame(item4, _itemsControl.Items[4]);
			Assert.AreSame(item5, _itemsControl.Items[5]);
		}

		[Test]
		[Ignore("Not yet implemented")]
		public void Index_ItemsShouldDynamicallyReflectChangesToIndex()
		{
			DependencyObject item1 = new DependencyObject();
			DependencyObject item2 = new DependencyObject();
			DependencyObject item3 = new DependencyObject();
			DependencyObject item4 = new DependencyObject();
			DependencyObject item5 = new DependencyObject();

			GroupingItemsControlUIAdapter.SetGroupIndex(item4, 1);
			GroupingItemsControlUIAdapter.SetGroupIndex(item5, 1);

			_groupingItemsControlUIAdapter.Add(item5);
			_groupingItemsControlUIAdapter.Add(item3);
			_groupingItemsControlUIAdapter.Add(item2);
			_groupingItemsControlUIAdapter.Add(item4);
			_groupingItemsControlUIAdapter.Add(item1);

			Assert.AreEqual(6, _itemsControl.Items.Count);
			Assert.AreSame(item3, _itemsControl.Items[0]);
			Assert.AreSame(item2, _itemsControl.Items[1]);
			Assert.AreSame(item1, _itemsControl.Items[2]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[4]);
			Assert.AreSame(item5, _itemsControl.Items[5]);
			Assert.AreSame(item4, _itemsControl.Items[6]);

			GroupingItemsControlUIAdapter.SetIndex(item1, 1);
			GroupingItemsControlUIAdapter.SetIndex(item2, 2);
			GroupingItemsControlUIAdapter.SetIndex(item3, 3);
			GroupingItemsControlUIAdapter.SetIndex(item5, 100);

			Assert.AreEqual(6, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);
			Assert.AreSame(item2, _itemsControl.Items[1]);
			Assert.AreSame(item3, _itemsControl.Items[2]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[3]);
			Assert.AreSame(item4, _itemsControl.Items[4]);
			Assert.AreSame(item5, _itemsControl.Items[5]);
		}

		[Test]
		[Ignore("Not yet implemented")]
		public void Visibility_ShouldAffectSeparatorVisibility()
		{
			UIElement item1 = new UIElement();
			UIElement item2 = new UIElement();
			UIElement item3 = new UIElement();
			UIElement item4 = new UIElement();
			UIElement item5 = new UIElement();

			GroupingItemsControlUIAdapter.SetGroupIndex(item2, 1);
			GroupingItemsControlUIAdapter.SetGroupIndex(item3, 1);
			GroupingItemsControlUIAdapter.SetGroupIndex(item4, 2);
			GroupingItemsControlUIAdapter.SetGroupIndex(item5, 2);

			_groupingItemsControlUIAdapter.Add(item1);
			_groupingItemsControlUIAdapter.Add(item2);
			_groupingItemsControlUIAdapter.Add(item3);
			_groupingItemsControlUIAdapter.Add(item4);
			_groupingItemsControlUIAdapter.Add(item5);

			Assert.AreEqual(7, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[1]);
			Assert.AreSame(item2, _itemsControl.Items[2]);
			Assert.AreSame(item3, _itemsControl.Items[3]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[4]);
			Assert.AreSame(item4, _itemsControl.Items[5]);
			Assert.AreSame(item5, _itemsControl.Items[6]);

			item1.Visibility = Visibility.Hidden;

			Assert.AreEqual(5, _itemsControl.Items.Count);
			Assert.AreSame(item2, _itemsControl.Items[0]);
			Assert.AreSame(item3, _itemsControl.Items[1]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[2]);
			Assert.AreSame(item4, _itemsControl.Items[3]);
			Assert.AreSame(item5, _itemsControl.Items[4]);

			item4.Visibility = Visibility.Hidden;

			Assert.AreEqual(4, _itemsControl.Items.Count);
			Assert.AreSame(item2, _itemsControl.Items[0]);
			Assert.AreSame(item3, _itemsControl.Items[1]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[2]);
			Assert.AreSame(item5, _itemsControl.Items[3]);

			item5.Visibility = Visibility.Hidden;

			Assert.AreEqual(2, _itemsControl.Items.Count);
			Assert.AreSame(item2, _itemsControl.Items[0]);
			Assert.AreSame(item3, _itemsControl.Items[1]);

			item1.Visibility = Visibility.Visible;

			Assert.AreEqual(4, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[1]);
			Assert.AreSame(item2, _itemsControl.Items[2]);
			Assert.AreSame(item3, _itemsControl.Items[3]);

			item2.Visibility = Visibility.Hidden;
			item3.Visibility = Visibility.Hidden;

			Assert.AreEqual(1, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);

			item4.Visibility = Visibility.Visible;

			Assert.AreEqual(3, _itemsControl.Items.Count);
			Assert.AreSame(item1, _itemsControl.Items[0]);
			Assert.IsInstanceOfType(typeof(Separator), _itemsControl.Items[1]);
			Assert.AreSame(item4, _itemsControl.Items[2]);
		}
	}
}
